#![allow(non_snake_case)]

use std::{backtrace::Backtrace, sync::Arc};

use super::exception::{ErrorCode, ErrorCodeBacktrace};

macro_rules! build_exceptions {
    ($($body:ident($code:expr)),*$(,)*) => {
            impl ErrorCode {
                $(
                pub fn $body(display_text: impl Into<String>) -> ErrorCode {
                    let bt = Some(ErrorCodeBacktrace::Origin(Arc::new(Backtrace::capture())));
                    ErrorCode::create(
                        $code,
                        display_text.into(),
                        None,
                        bt,
                    )
                }
                paste::item! {
                    pub fn [< $body:snake _ code >] ()  -> u16{
                        $code
                    }

                    pub fn [< $body  Code >] ()  -> u16{
                        $code
                    }
                }
                )*
            }
    }
}

// Internal errors [0, 2000].
build_exceptions! {
    Ok(0),
    UnImplement(1001),
    BadAddressFormat(1002),
    OutOfBounds(1002),
    UnknownException(1999),
}

// Common errors [2001,2100].
build_exceptions! {
    // A task that already stopped and can not stop twice.
    AlreadyStarted(2001),

    // A task that already started and can not start twice.
    AlreadyStopped(2002),

    RequestInvalid(2003),

    IllegalStateError(2004),
}

// Db errors [2101,2200].
build_exceptions! {
    DbConfigNotFound(2101),

    DbTypeNotSupport(2102),

    DbFieldNotSupport(2103),

    DbInnerError(2104),

    DbConnectionNotFound(2105),

}

// Invoke errors [2201,2300].
build_exceptions! {
    EaiServerNotFound(2201),

    InvokerNotFound(2202),

    RemoteInvokerError(2203),
}

// Service errors [2301,2400].
build_exceptions! {
    ServiceKeyInvalid(2301),

    ServiceNotFound(2302),

    DylibLoadFailed(2303),

    PluginParamTypeInvalid(2304),
}
